package com.example.micro_property_springboot.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.micro_property_springboot.mapper.AssetCheckItemMapper;
import com.example.micro_property_springboot.mapper.AssetCheckPlanMapper;
import com.example.micro_property_springboot.mapper.AssetInfoMapper;
import com.example.micro_property_springboot.pojo.AssetCheckItem;
import com.example.micro_property_springboot.pojo.AssetInfo;
import com.example.micro_property_springboot.pojo.DTO.request.AssetCheckItemRequest;
import com.example.micro_property_springboot.service.AssetCheckItemService;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 资产盘点项服务实现类
 */
@Slf4j
@Service
public class AssetCheckItemServiceImpl extends ServiceImpl<AssetCheckItemMapper, AssetCheckItem> implements AssetCheckItemService {

    @Autowired
    private AssetInfoMapper assetInfoMapper;

    @Autowired
    private AssetCheckItemMapper assetCheckItemMapper;

    @Override
    @Transactional
    public void createAssetCheckItems(Long planId, List<Long> assetIds) {
        log.info("为盘点计划ID: {} 创建盘点明细，资产数量: {}", planId, assetIds != null ? assetIds.size() : 0);

        if (assetIds == null || assetIds.isEmpty()) {
            log.warn("资产ID列表为空，跳过创建盘点明细");
            return;
        }

        // 验证资产是否存在
        List<AssetInfo> validAssets = validateAssets(assetIds);
        if (validAssets.isEmpty()) {
            log.error("指定的资产ID列表中没有有效的资产");
            throw new RuntimeException("指定的资产ID列表中没有有效的资产");
        }

        // 检查是否已存在盘点明细
        List<AssetCheckItem> existingItems = getExistingCheckItems(planId, assetIds);
        List<Long> existingAssetIds = existingItems.stream()
                .map(AssetCheckItem::getAssetId)
                .collect(Collectors.toList());

        // 过滤出需要创建的资产ID
        List<Long> newAssetIds = assetIds.stream()
                .filter(assetId -> !existingAssetIds.contains(assetId))
                .collect(Collectors.toList());

        if (newAssetIds.isEmpty()) {
            log.info("所有资产已存在于盘点计划中，无需重复创建");
            return;
        }

        // 创建新的盘点明细
        List<AssetCheckItem> items = new ArrayList<>();
        for (Long assetId : newAssetIds) {
            AssetCheckItem item = new AssetCheckItem();
            item.setPlanId(planId);
            item.setAssetId(assetId);
            item.setCheckStatus("UNCHECKED");
            item.setCheckTime(null);
            item.setCheckUserId(null);
            item.setRemark("待盘点");
            item.setCreateTime(LocalDateTime.now());
            items.add(item);
        }

        saveBatch(items);
        log.info("成功创建{}条盘点明细，计划ID: {}", items.size(), planId);
    }

    /**
     * 验证资产是否存在且状态正常
     */
    private List<AssetInfo> validateAssets(List<Long> assetIds) {
        QueryWrapper<AssetInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id", assetIds);
        queryWrapper.in("status", "正常", "使用中"); // 只允许盘点正常状态的资产
        return assetInfoMapper.selectList(queryWrapper);
    }

    /**
     * 获取已存在的盘点明细
     */
    private List<AssetCheckItem> getExistingCheckItems(Long planId, List<Long> assetIds) {
        QueryWrapper<AssetCheckItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("plan_id", planId);
        queryWrapper.in("asset_id", assetIds);
        return list(queryWrapper);
    }

    /**
     * 执行资产盘点
     * @param planId 盘点计划ID
     * @param request 资产盘点请求
     * @param userId 当前用户ID
     * @return 资产盘点明细
     */
    @Override
    @Transactional
    public AssetCheckItem checkAsset(Long planId, AssetCheckItemRequest request, Long userId) {
        log.info("执行资产盘点，计划ID: {}, 资产ID: {}, 用户ID: {}",
                planId, request.getAssetId(), userId);

        // 验证请求参数
        validateCheckRequest(planId, request, userId);

        QueryWrapper<AssetCheckItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("plan_id", planId);
        queryWrapper.eq("asset_id", request.getAssetId());

        AssetCheckItem item = getOne(queryWrapper);
        if (item == null) {
            throw new RuntimeException("该资产不在当前盘点计划中，请先添加到盘点计划");
        }

        // 检查是否已盘点
        if ("CHECKED".equals(item.getCheckStatus())) {
            throw new RuntimeException("该资产已被盘点，无法重复盘点");
        }

        // 更新盘点信息
        item.setCheckStatus("CHECKED");
        item.setCheckTime(LocalDateTime.now());
        item.setCheckUserId(userId);
        item.setRemark(request.getRemark());

        saveOrUpdate(item);

        log.info("资产盘点完成，明细ID: {}, 资产ID: {}", item.getId(), request.getAssetId());

        return item;
    }

    /**
     * 验证盘点请求参数
     */
    private void validateCheckRequest(Long planId, AssetCheckItemRequest request, Long userId) {
        if (planId == null || planId <= 0) {
            throw new RuntimeException("盘点计划ID不能为空");
        }
        if (request.getAssetId() == null || request.getAssetId() <= 0) {
            throw new RuntimeException("资产ID不能为空");
        }
        if (userId == null || userId <= 0) {
            throw new RuntimeException("用户ID不能为空");
        }

        // 验证资产是否存在
        AssetInfo assetInfo = assetInfoMapper.selectById(request.getAssetId());
        if (assetInfo == null) {
            throw new RuntimeException("资产不存在，ID: " + request.getAssetId());
        }

        // 验证资产状态是否允许盘点
        if (!isAssetStatusValidForCheck(assetInfo.getStatus())) {
            throw new RuntimeException("资产状态不允许盘点，当前状态: " + assetInfo.getStatus());
        }
    }

    /**
     * 检查资产状态是否允许盘点
     */
    private boolean isAssetStatusValidForCheck(String status) {
        return "正常".equals(status) || "使用中".equals(status) || "闲置".equals(status);
    }

    /**
     * 获取盘点明细列表
     * @param planId 盘点计划ID
     * @param checkStatus 盘点状态
     * @return 盘点明细列表
     */
    @Override
    public List<AssetCheckItem> getAssetCheckItems(Long planId, String checkStatus) {
        log.info("获取盘点明细列表，计划ID: {}, 状态: {}", planId, checkStatus);

        QueryWrapper<AssetCheckItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("plan_id", planId);

        if (checkStatus != null && !checkStatus.isEmpty()) {
            queryWrapper.eq("check_status", checkStatus);
        }

        queryWrapper.orderByDesc("create_time");
        return list(queryWrapper);
    }

    @Override
    public Map<String, Integer> getCheckProgress(Long planId) {
        log.info("获取盘点进度，计划ID: {}", planId);

        QueryWrapper<AssetCheckItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("plan_id", planId);

        int total = (int) count(queryWrapper);

        queryWrapper.eq("check_status", "CHECKED");
        int checked = (int) count(queryWrapper);

        int unchecked = total - checked;
        double progressRate = total > 0 ? (double) checked / total * 100 : 0;

        Map<String, Integer> progress = new HashMap<>();
        progress.put("total", total);
        progress.put("checked", checked);
        progress.put("unchecked", unchecked);
        progress.put("progressRate", (int) progressRate);

        log.info("盘点进度统计 - 总数: {}, 已盘点: {}, 未盘点: {}, 完成率: {}%",
                total, checked, unchecked, (int) progressRate);

        return progress;
    }

    /**
     * 批量处理资产盘点
     * @param planId 盘点计划ID
     * @param requests 资产盘点请求列表
     * @param userId 当前用户ID
     * @return 处理后的资产盘点明细列表
     */
    @Override
    public List<AssetCheckItem> batchCheckAssets(Long planId, List<AssetCheckItemRequest> requests, Long userId) {
        log.info("批量处理资产盘点，计划ID: {}, 资产数量: {}, 用户ID: {}", planId, requests.size(), userId);


        if (requests == null || requests.isEmpty()) {
            throw new RuntimeException("资产盘点请求列表不能为空");
        }

        // 验证资产是否存在
        List<Long> assetIds = requests.stream()
                .map(AssetCheckItemRequest::getAssetId)
                .collect(Collectors.toList());

        List<AssetInfo> assetInfos = assetInfoMapper.selectBatchIds(assetIds);
        if (assetInfos.size() != assetIds.size()) {
            throw new RuntimeException("存在不存在的资产ID");
        }

        // 执行批量盘点
        List<AssetCheckItem> checkedItems = new ArrayList<>();
        for (AssetCheckItemRequest request : requests) {
            AssetCheckItem item = checkAsset(planId, request, userId);
            checkedItems.add(item);
        }

        log.info("批量处理资产盘点完成，处理数量: {}", checkedItems.size());
        return checkedItems;
    }

    /**
     * 重置资产盘点状态
     * @param planId 盘点计划ID
     */
    @Override
    public void resetCheckStatus(Long planId) {
        log.info("重置资产盘点状态，计划ID: {}", planId);

        QueryWrapper<AssetCheckItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("plan_id", planId);
        AssetCheckItem assetCheckItem = new AssetCheckItem();
        assetCheckItem.setCheckStatus("UNCHECKED");
        assetCheckItem.setCheckTime(null);
        assetCheckItem.setCheckUserId(null);
        assetCheckItem.setRemark("重置为待盘点");
        assetCheckItem.setCreateTime(LocalDateTime.now());

        update(assetCheckItem, queryWrapper);

        log.info("资产盘点状态重置完成，计划ID: {}", planId);
    }

    @Override
    public Map<String, Object> getCheckStatistics(Long planId) {
        log.info("获取资产盘点统计信息，计划ID: {}", planId);

        QueryWrapper<AssetCheckItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("plan_id", planId);

        int total = (int) count(queryWrapper);

        queryWrapper.eq("check_status", "CHECKED");
        int checked = (int) count(queryWrapper);

        int unchecked = total - checked;

        Map<String, Object> statistics = new HashMap<>();
        statistics.put("total", total);
        statistics.put("checked", checked);
        statistics.put("unchecked", unchecked);

        log.info("资产盘点统计信息 - 总数: {}, 已盘点: {}, 未盘点: {}", total, checked, unchecked);

        return statistics;
    }

    /**
     * 获取盘点明细详情（包含资产信息）
     */
    public List<Map<String, Object>> getAssetCheckItemsWithAssetInfo(Long planId, String checkStatus) {
        log.info("获取盘点明细详情（包含资产信息），计划ID: {}, 状态: {}", planId, checkStatus);

        List<AssetCheckItem> checkItems = getAssetCheckItems(planId, checkStatus);

        List<Map<String, Object>> result = new ArrayList<>();
        for (AssetCheckItem item : checkItems) {
            Map<String, Object> itemWithAsset = new HashMap<>();
            itemWithAsset.put("checkItem", item);

            // 获取资产信息
            AssetInfo assetInfo = assetInfoMapper.selectById(item.getAssetId());
            itemWithAsset.put("assetInfo", assetInfo);

            result.add(itemWithAsset);
        }

        return result;
    }

    /**
     * 批量标记资产为已盘点
     */
    @Transactional
    public void batchCheckAssets(Long planId, List<Long> assetIds, Long userId, String remark) {
        log.info("批量盘点资产，计划ID: {}, 资产数量: {}, 用户ID: {}", planId, assetIds.size(), userId);

        if (assetIds == null || assetIds.isEmpty()) {
            throw new RuntimeException("资产ID列表不能为空");
        }

        QueryWrapper<AssetCheckItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("plan_id", planId);
        queryWrapper.in("asset_id", assetIds);
        queryWrapper.eq("check_status", "UNCHECKED");

        List<AssetCheckItem> items = list(queryWrapper);
        if (items.isEmpty()) {
            log.warn("没有找到待盘点的资产");
            return;
        }

        LocalDateTime now = LocalDateTime.now();
        for (AssetCheckItem item : items) {
            item.setCheckStatus("CHECKED");
            item.setCheckTime(now);
            item.setCheckUserId(userId);
            item.setRemark(remark != null ? remark : "批量盘点");
            item.setCreateTime(now);
        }

        updateBatchById(items);
        log.info("批量盘点完成，处理数量: {}", items.size());
    }

    /**
     * 重置盘点状态（将已盘点重置为未盘点）
     */
    @Transactional
    public void resetCheckStatus(Long planId, List<Long> assetIds) {
        log.info("重置盘点状态，计划ID: {}, 资产数量: {}", planId, assetIds != null ? assetIds.size() : "全部");

        QueryWrapper<AssetCheckItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("plan_id", planId);
        queryWrapper.eq("check_status", "CHECKED");

        if (assetIds != null && !assetIds.isEmpty()) {
            queryWrapper.in("asset_id", assetIds);
        }

        List<AssetCheckItem> items = list(queryWrapper);
        if (items.isEmpty()) {
            log.warn("没有找到已盘点的资产");
            return;
        }

        for (AssetCheckItem item : items) {
            item.setCheckStatus("UNCHECKED");
            item.setCheckTime(null);
            item.setCheckUserId(null);
            item.setRemark("重置为待盘点");
            item.setCreateTime(LocalDateTime.now());
        }

        updateBatchById(items);
        log.info("重置盘点状态完成，处理数量: {}", items.size());
    }

    /**
     * 删除盘点明细
     */
    @Transactional
    public void deleteAssetCheckItems(Long planId, List<Long> assetIds) {
        log.info("删除盘点明细，计划ID: {}, 资产数量: {}", planId, assetIds.size());

        if (assetIds == null || assetIds.isEmpty()) {
            throw new RuntimeException("资产ID列表不能为空");
        }

        QueryWrapper<AssetCheckItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("plan_id", planId);
        queryWrapper.in("asset_id", assetIds);

        int deletedCount = assetCheckItemMapper.delete(queryWrapper);
        log.info("删除盘点明细完成，删除数量: {}", deletedCount);
    }
}